package xyz.zdsoft.training_manage_system.filter;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import xyz.zdsoft.auth_module.utils.UserList;
import xyz.zdsoft.common.auth.UserType;
import xyz.zdsoft.common.exception.BizException;
import xyz.zdsoft.common.utils.JwtUtils;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Session过滤器，对特定路由的访问进行拦截
 * 部分路由必须要经过权限认证才可放行
 */
@WebFilter(filterName = "SessionFilter", urlPatterns = "/*")
public class SessionFilter implements Filter {

    private final List<UserType> userTypes = new ArrayList<>();

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        userTypes.add(UserType.USER_TYPE_A_T_S);
        userTypes.add(UserType.USER_TYPE_STUDENT);
        userTypes.add(UserType.USER_TYPE_TEACHER);
        userTypes.add(UserType.USER_TYPE_ADMIN);
        userTypes.add(UserType.USER_TYPE_A_T);
        userTypes.add(UserType.USER_TYPE_T_S);
        userTypes.add(UserType.USER_TYPE_A_S);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Expose-Headers","token");

        if (request.getMethod().equals(HttpMethod.OPTIONS.name())){
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return;
        }
        String uri = request.getRequestURI();
        // 从路由中匹配访问该路由需要的用户类型权限
        // 访问的原则是，当路由中包含admin、student、teacher时，则需要对应的session认证
        UserType pathUserType = matchUserType(uri);
        // 该路由不包含需要认证
        if (pathUserType == null) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        String token =  request.getHeader("Authorization");
//        String token =  JwtUtils.getJwtToken("123456","student");
        if (!(token == null || token.equals(""))&&JwtUtils.checkCookie(token)) {
            //使用map来存储已登录用户
//            if(UserList.getInstance().getUser(token)==null){
            //使用Redis来存储已登录的用户
            if(redisTemplate.opsForValue().get(token)==null){
                response.sendError(HttpStatus.UNAUTHORIZED.value());
                return;
            }
            String userType = JwtUtils.getMemberUserTypeByJwtToken(token);
            if (UserType.userAuthentication(pathUserType.getName(),userType)){
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            //403
            response.sendError(HttpStatus.FORBIDDEN.value());
            return;
        }
        //401
        response.sendError(HttpStatus.UNAUTHORIZED.value());
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    private UserType matchUserType(String uri) {
        // FIX: 不用contains，不然会有命名冲突
        return userTypes.stream().filter(userType -> Arrays.stream(uri.split("/")).anyMatch(seg -> seg.equals(userType.getName())))
                .findFirst().orElse(null);
    }
}